// Created by amoylel on 12/18/2018.
// Copyright (c) 2018 amoylel All rights reserved.

#ifndef AMO_STRING_CONVERT_BOOST_1BE1864E_4DE2_4B27_B526_A36D62DE490E_HPP__
#define AMO_STRING_CONVERT_BOOST_1BE1864E_4DE2_4B27_B526_A36D62DE490E_HPP__


#include <string>
#include <unordered_map>
#include <regex>
#include <algorithm>

#include <amo/string/coding_type.hpp>
#include <amo/string/string_algo.hpp>

#include <boost/locale.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/util.hpp>
#include <boost/locale.hpp>

//#include <codecvt>


namespace amo {
    namespace string_utils {
    
    
        static std::locale  get_system_locale() {
            std::string code_page = boost::locale::util::get_system_locale();
            return boost::locale::generator().generate(code_page);
        }
        
        static bool  is_utf8_system() {
            std::string from_encoding = std::use_facet<boost::locale::info>
                                        (get_system_locale()).encoding();
                                        
            from_encoding = amo::string_utils::to_upper(from_encoding);
            
            if (from_encoding.find("UTF-8") != -1) {
                return true;
            }
            
            if (from_encoding.find("UTF8") != -1) {
                return true;
            }
            
            return false;
        }
        
        static std::string ansi_to_utf8(const std::string& src) {
            std::string from_encoding = std::use_facet<boost::locale::info>
                                        (get_system_locale()).encoding();
            return  boost::locale::conv::between(src, "UTF-8", from_encoding);
        }
        
        static std::wstring ansi_to_wide(const std::string& src) {
            return  boost::locale::conv::to_utf<wchar_t>(src, get_system_locale());
        }
        
        static std::wstring utf8_to_wide(const std::string& src) {
            return  boost::locale::conv::utf_to_utf<wchar_t>(src);
        }
        
        static std::string utf8_to_ansi(const std::string& src) {
            std::string from_encoding = std::use_facet<boost::locale::info>
                                        (get_system_locale()).encoding();
            return  boost::locale::conv::from_utf(src, from_encoding);
        }
        
        static std::string wide_to_ansi(const std::wstring& src) {
            std::string from_encoding = std::use_facet<boost::locale::info>
                                        (get_system_locale()).encoding();
            return boost::locale::conv::from_utf(src, from_encoding);
        }
        
        static std::string wide_to_utf8(const std::wstring& src) {
            return boost::locale::conv::utf_to_utf<char>(src);
        }
        
        
        
        static std::string utf8_to_string(const std::string& utf8string,
                                          StringCodingType codingtype) {
            switch (codingtype) {
            case amo::CODING_TYPE_ANSI:
                return utf8_to_ansi(utf8string);
                
            case amo::CODING_TYPE_UNKNOWN:
            case amo::CODING_TYPE_UTF8:
            default:
                return utf8string;
            }
        }
        
        static std::string ansi_to_string(const std::string& ansistring,
                                          StringCodingType codingtype) {
            switch (codingtype) {
            case amo::CODING_TYPE_UTF8:
                return ansi_to_utf8(ansistring);
                
            case amo::CODING_TYPE_UNKNOWN:
            case amo::CODING_TYPE_ANSI:
            default:
                return ansistring;
            }
        }
        
        static std::string wide_to_string(const std::wstring& widestring,
                                          StringCodingType codingtype) {
            switch (codingtype) {
            case amo::CODING_TYPE_UTF8:
                return wide_to_utf8(widestring);
                
            case amo::CODING_TYPE_UNKNOWN:
            case amo::CODING_TYPE_ANSI:
            default:
                return wide_to_ansi(widestring);
            }
        }
        
        static std::wstring string_to_wide(const std::string& anystring,
                                           StringCodingType codingtype) {
                                           
            switch (codingtype) {
            case amo::CODING_TYPE_UTF8:
                return utf8_to_wide(anystring);
                
            case amo::CODING_TYPE_ANSI:
            case amo::CODING_TYPE_UNKNOWN:
            default:
                return ansi_to_wide(anystring);
            }
        }
        
        static std::string string_to_utf8(const std::string& anystring,
                                          StringCodingType codingtype) {
                                          
            switch (codingtype) {
            case amo::CODING_TYPE_ANSI:
                return ansi_to_utf8(anystring);
                
            case amo::CODING_TYPE_UTF8:
            case amo::CODING_TYPE_UNKNOWN:
            default:
                return anystring;
            }
        }
        
        
        static std::string string_to_ansi(const std::string& anystring,
                                          StringCodingType codingtype) {
                                          
            switch (codingtype) {
            case amo::CODING_TYPE_UTF8:
                return utf8_to_ansi(anystring);
                
            case amo::CODING_TYPE_ANSI:
            
            case amo::CODING_TYPE_UNKNOWN:
            default:
                return anystring;
            }
        }
        
        
        
    }
}

#endif // AMO_STRING_CONVERT_BOOST_1BE1864E_4DE2_4B27_B526_A36D62DE490E_HPP__

